package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"strings"
)

func main()  {
	//bufioReadMain()
	//bufioWriteMain()
	//bufioReadWriterMain()
	//bufioScanMain()
	bufioScanExampleMain()
}

func bufioReadMain()  {
	// 创建一个具有默认大小缓冲、从r读取的*Reader。
	bufioNewReader := bufio.NewReader(strings.NewReader("aaabbbcccddd"))

	// 创建一个 size 字节的缓冲并从 rd 中读取数据
	bufioNewReaderSize := bufio.NewReaderSize(strings.NewReader("aaabbbcccddd"),20)
	fmt.Println(bufioNewReaderSize.Size())

	// 返回缓冲区的大小,并不是存放里面的数据大小
	bufioReaderSize := bufioNewReader.Size()
	fmt.Println(bufioReaderSize)

	// 重置缓冲区
	bufioNewReader.Reset(strings.NewReader("eeefffggg"))

	// 返回缓存区的 n 个字节，并且不移动缓存区的读取位置
	bufioReaderPeek,_ := bufioNewReader.Peek(12)
	fmt.Println(string(bufioReaderPeek))

	// 丢弃缓冲区的 n 个字节，并还回被丢弃的字节数量
	bufioReaderDiscard,_ := bufioNewReader.Discard(3)
	fmt.Println(bufioReaderDiscard)

	bufioNewReader.Reset(strings.NewReader("eeefffggghhh"))
	// 读取缓冲区的数据到 p 中,返回读取的字节数
	bufioNewReaderRead := []byte("aaabbb")
	bufioReaderRead,_ := bufioNewReader.Read(bufioNewReaderRead)
	fmt.Println((string(bufioNewReaderRead)))
	fmt.Println(bufioReaderRead)

	// 读取并返回一个字节
	bufioReaderReadByte,_ := bufioNewReader.ReadByte()
	fmt.Println(string(bufioReaderReadByte))

	// 取出最近一次读取操作读取的最后一个字节
	bufioNewReader.UnreadByte()

	// 读取一个utf-8编码的unicode码值，返回该码值、其编码长度
	bufioReaderReadRuneRune,bufioReaderReadRuneInt,_ := bufioNewReader.ReadRune()
	fmt.Println(bufioReaderReadRuneRune,bufioReaderReadRuneInt)

	// 出最近一次ReadRune调用读取的unicode码值
	bufioNewReader.UnreadRune()

	// 返回可以从当前缓冲区读取的字节数
	bufioReadBuffered := bufioNewReader.Buffered()
	fmt.Println(bufioReadBuffered)

	// 返回读缓冲区读取到的 delim 为止读取的字节，包含delim 字节切片
	bufioReadReadSlice,_ := bufioNewReader.ReadSlice('h')
	fmt.Println(string(bufioReadReadSlice))

	// 返回行，但是不会返回行结束符，若行太长超出缓冲，则分多次返回
	// 应使用ReadBytes('\n')或ReadString('\n')代替
	bufioReadReadLineLine,bufioReadReadLineIsprefix,_ := bufioNewReader.ReadLine()
	fmt.Println(string(bufioReadReadLineLine),bufioReadReadLineIsprefix)

	bufioNewReader.Reset(strings.NewReader("eeefffggghhh"))
	// 返回读缓冲区读取到的 delim 为止读取的字节，包含delim 字节切片
	bufioReadReadBytes,_ := bufioNewReader.ReadBytes('h')
	fmt.Println(string(bufioReadReadBytes))

	bufioNewReader.Reset(strings.NewReader("eeefffggghhh"))
	// 返回读缓冲区读取到的 delim 为止读取的字节，包含delim 字符串
	bufioReadReadString,_ := bufioNewReader.ReadString('h')
	fmt.Println(bufioReadReadString)

	// 实现 io.WriteTo 接口
	bufioReadWriteTo,_ := bufioNewReader.WriteTo(os.Stdout)
	fmt.Println(bufioReadWriteTo)
}

func bufioWriteMain()  {
	var buf bytes.Buffer
	// 缓冲区大小为默认值的新Writer。
	bufioNewWriter := bufio.NewWriter(&buf)

	// 创建一个 size 缓冲的 writer
	bufioNewWriterSize := bufio.NewWriterSize(&buf,20)
	fmt.Println(bufioNewWriterSize.Size())

	// 返回基础缓冲区的大小（字节）
	bufioWriterSize := bufioNewWriter.Size()
	fmt.Println(bufioWriterSize)

	// 重置缓冲区
	bufioNewWriter.Reset(os.Stdout)

	// 将所有缓冲数据写入基础io
	bufioNewWriter.Flush()

	bufioNewWriter.WriteString("aaabbbccc")
	// 返回缓冲区中未使用的字节数。
	bufioWriterAvaiable := bufioNewWriter.Available()
	fmt.Println(bufioWriterAvaiable)

	// 返回缓冲区未使用的字节切片
	bufioWriterAvaiableBuffer := bufioNewWriter.AvailableBuffer()
	fmt.Println(string(bufioWriterAvaiableBuffer))

	// 返回已写入当前缓冲区的字节数。
	bufioWriterBuffer := bufioNewWriter.Buffered()
	fmt.Println(bufioWriterBuffer)

	// 将 p 的内容写入缓冲区，返回写入的字节数
	bufioWriterWriter,_ := bufioNewWriter.Write([]byte("hello the world"))
	fmt.Println(bufioWriterWriter)

	// 写入一个字节
	bufioNewWriter.WriteByte('a')

	// 写入单个Unicode代码点，返回 写入的字节数
	bufioWriterWriterRune,_ := bufioNewWriter.WriteRune('a')
	fmt.Println(bufioWriterWriterRune)

	// 写入字符串，并返回写入的字节数
	bufioWriterWriterString,_ := bufioNewWriter.WriteString("aaabbbccc")
	fmt.Println(bufioWriterWriterString)

	// 实现了io.ReaderFrom接口
	bufioWriteReadFrom,_ := bufioNewWriter.ReadFrom(strings.NewReader("dddeeefff"))
	fmt.Println(bufioWriteReadFrom)
}

func bufioReadWriterMain()  {
	bufioNewReader := bufio.NewReader(strings.NewReader("aaabbbcccddd"))
	var buf bytes.Buffer
	bufioNewWriter := bufio.NewWriter(&buf)

	// 创建一个新的 ReadWriter
	bufioNewReadWriter := bufio.NewReadWriter(bufioNewReader,bufioNewWriter)
	fmt.Println(bufioNewReadWriter.Read([]byte("eeefffggghhh")))
}

func bufioScanMain()  {
	// 定义扫描器分割函数
	onComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
		for i := 0; i < len(data); i++ {
			if data[i] == ',' {

				return i + 1, data[:i], nil

			}
		}

		// 最后一个可能是空字符串，error传入ErrFinalToken告诉bufio是最后个，使其不报错。
		return 0, data, bufio.ErrFinalToken
	}

	//  创建一个新的扫描器
	bufioScanNew := bufio.NewScanner(strings.NewReader("1,2,3,4,"))

	// 设置该Scanner的分割函数。本方法必须在Scan之前调用
	bufioScanNew.Split(onComma)

	// 设置扫描时使用的初始缓冲区，以及扫描期间可能分配的最大缓冲区大小
	bufioScanNew.Buffer([]byte("5,6,7,8,9,"),20)

	// 返回扫描器生成的 token
	bufioScanBytes := bufioScanNew.Bytes()
	fmt.Println(string(bufioScanBytes))

	// 返回扫描器生成的 token
	bufioScanString := bufioScanNew.Text()
	fmt.Println(bufioScanString)

	// 获取当前的 token ，并让扫描器移动到下一个token
	bufioScanScan := bufioScanNew.Scan()
	fmt.Println(bufioScanScan)

	// 返回扫描器遇到的第一个非 io.EOF 错误
	bufioScanNew.Err()

	// 扫描拆分函数，它将每个字节作为令牌返回
	bufioScanBytesAdvance,bufioScanBytesToken,_ := bufio.ScanBytes([]byte("10,11,12,13,14,15"),true)
	fmt.Println(bufioScanBytesAdvance,string(bufioScanBytesToken))

	// 扫描拆分函数，它将每个UTF-8编码的rune作为令牌返回
	bufioScanRunesAdvance,bufioScanRunesToken,_ := bufio.ScanRunes([]byte("10,11,12,13,14,15"),true)
	fmt.Println(bufioScanRunesAdvance,string(bufioScanRunesToken))

	//扫描拆分函数， 返回每行文本，并去除行尾标记
	bufioScanLinesAdvance,bufioScanLinesToken,_ := bufio.ScanLines([]byte("10,11,12,13,14,15\n"),true)
	fmt.Println(bufioScanLinesAdvance,string(bufioScanLinesToken))

	// 扫描拆分函数， 返回文本中每个以空格分隔的单词，并删除周围的空格
	bufioScanWordsAdvance,bufioScanWordsToken,_ := bufio.ScanWords([]byte("10 , 11 , 12,13,14,15\n"),true)
	fmt.Println(bufioScanWordsAdvance,string(bufioScanWordsToken))

}

func bufioScanExampleMain()  {
	scanner := bufio.NewScanner(strings.NewReader("10 , 11 , 12,13,14,15\n,1, 2, 3,4,5,6\n"))
	//scanner.Split(bufio.ScanWords)
	//scanner.Split(bufio.ScanLines)
	//scanner.Split(bufio.ScanRunes)
	scanner.Split(bufio.ScanBytes)
	for scanner.Scan() {
		//fmt.Printf("%s\n", scanner.Bytes())
		fmt.Println(scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		fmt.Println(err)
	}
}
